package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import com.zmj.sy.mom.srv.aps.bean.entity.base.BaseEntity;
import com.zmj.sy.mom.srv.aps.bean.entity.mes.*;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsOrder;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkDetail;
import com.zmj.sy.mom.srv.aps.bean.entity.order.ApsWorkOrder;
import com.zmj.sy.mom.srv.aps.bean.entity.order.Order;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPart;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestPlate;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdsReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseListResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.plate.*;
import com.zmj.sy.mom.srv.aps.config.ProjectConfig;
import com.zmj.sy.mom.srv.aps.feign.ApsMesFeign;
import com.zmj.sy.mom.srv.aps.feign.StaffApiClient;
import com.zmj.sy.mom.srv.aps.feign.WmsApiClient;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class PlateService {

    private final SinoCamReceiveNestPlateMapper sinoCamReceiveNestPlateMapper;

//    private final SinoCamReceiveNestNestMapper sinoCamReceiveNestNestMapper;

    private final PlateMapper plateMapper;
    private final StationService stationService;
    private final StaffApiClient staffApiClient;
    private final  ApsMesFeign apsMesFeign;
    private final SinoCamReceiveNestPartMapper sinoCamReceiveNestPartMapper;

    private final ApsWorkDetailMapper apsWorkDetailMapper;

    private final ApsWorkOrderMapper apsWorkOrderMapper;

    private final OrderMapper orderMapper;

    private final ApsOrderMapper apsOrderMapper;

    private final ProjectConfig projectConfig;

    private final WmsPlatePickMapper wmsPlatePickMapper;
    private final WorkRecordMapper workRecordMapper;

    private final SinoCamReceiveNestMapper sinoCamReceiveNestMapper;

    private final WmsApiClient wmsApiClient;
    private final PartMapper partMapper;
    private final PlateUtils plateUtils;
    private final PartLogMapper partLogMapper;
    private final StringRedisTemplate stringRedisTemplate;
    private final Environment environment;
    private final SerialCodeUtils serialCodeUtils;
    private final WorkDetailTaskMapper workDetailTaskMapper;
    private final PlatePhaseMapper platePhaseMapper;
    private final PartUtilService partUtilService;

    @Transactional
    public void pick(BaseIdsReqVo reqVo) {

        // 生成领料单
        String max = serialCodeUtils.pickPlate();

        int seq = 1;
        List<WmsPlatePick> platePickList = wmsPlatePickMapper.selectBatchIds(reqVo.getIds());
        for (WmsPlatePick wmsPlatePick : platePickList) {
            wmsPlatePickMapper.lambdaUpdate()
                    .eq(BaseEntity::getId, wmsPlatePick.getId())
                    .set(WmsPlatePick::getPlateState, 2)
                    .set(WmsPlatePick::getPickUserId, 1)
                    .set(WmsPlatePick::getPickUserName, "佚名")
                    .set(WmsPlatePick::getPickingListNo, max)
                    .set(WmsPlatePick::getPickListItem, seq)
                    .set(WmsPlatePick::getPickDateTime, LocalDateTime.now())
                    .update();
            wmsPlatePick.setPickingListNo(max);
            wmsPlatePick.setPickListItem(seq);
//            wmsPlatePick.setPackageSn(max.toString());
            seq++;

            plateMapper.lambdaUpdate()
                    .eq(Plate::getId, wmsPlatePick.getPlateId())
                    .set(Plate::getStatus, 2)
                    .update();
        }

        // 发送到 WMS 生成领料单
        wmsApiClient.sendLingliao(platePickList);

        /* 以前打包的逻辑
        // 判断是一个还是一包
        if (!projectConfig.isPackageType()) {
            return ;
        }

        List<WmsPlatePick> temp = getWmsPlatePicks(platePickList);

        if(CollUtil.isEmpty(temp)){
            return ;
        }

        String packSn = LocalTime.now().format(DatePattern.PURE_TIME_FORMATTER);
        for (int i = 0; i < temp.size(); i++) {
            wmsPlatePickMapper.lambdaUpdate()
                    .eq(BaseEntity::getId, temp.get(i).getId())
                    .set(WmsPlatePick::getPackageSn, packSn)
                    .set(WmsPlatePick::getPickListItem, i + 1)
                    .set(WmsPlatePick::getPlateState, 2)
                    .set(WmsPlatePick::getPickUserId, 1)
                    .set(WmsPlatePick::getPickUserName, "佚名")
                    .set(WmsPlatePick::getPickDateTime, LocalDateTime.now())
                    .update();

            plateMapper.lambdaUpdate()
                    .eq(Plate::getId, temp.get(i).getPlateId())
                    .set(Plate::getStatus, 2)
                    .update();
        }
        */

//        pickJob();

    }

    public BasePageResVo<PlatePickListResVo> pickList(PlatePickListReqVo reqVo) {

        Page<WmsPlatePick> page = wmsPlatePickMapper.query()
                .lt(reqVo.getStatus() != null, "plate_state", 4)
                .ge(reqVo.getStatus() == null, "plate_state", 4)
                .like(StringUtils.hasText(reqVo.getMaterCode()), "material_id", reqVo.getMaterCode())
                .like(StringUtils.hasText(reqVo.getStorehouseId()), "storage_place", reqVo.getStorehouseId())
                .like(StringUtils.hasText(reqVo.getNestId()), "nest_id", reqVo.getNestId())
                .like(StringUtils.hasText(reqVo.getPickingListNo()), "picking_list_no", reqVo.getPickingListNo())
                .eq(reqVo.getLayer() != null, "seq", reqVo.getLayer())
                /* .eq(reqVo.getStatus()!=null,"plate_state", reqVo.getStatus()!=null?reqVo.getStatus():null)
                 .gt(reqVo.getStatus()==null,"plate_state", 1)*/
                .orderByDesc("id")
                .page(reqVo.toPage());
        if(CollUtil.isEmpty(page.getRecords())){
            return BasePageResVo.empty();
        }

        List<SinoCamReceiveNestPlate> plateList = sinoCamReceiveNestPlateMapper.lambdaQuery().in(SinoCamReceiveNestPlate::getStockListNo,page.getRecords().stream().map(e->e.getMaterialId()).collect(Collectors.toList()) ).list();
        Map<String, SinoCamReceiveNestPlate> map = plateList.stream().collect(Collectors.toMap(SinoCamReceiveNestPlate::getStockListNo, Function.identity()));

        List<PlatePickListResVo> collect = page.getRecords()
                .stream()
                .map(e -> {
                    PlatePickListResVo r = new PlatePickListResVo();
                    r.setId(e.getId());
                    r.setMaterCode(e.getMaterialId());
                    r.setMaterName("钢板");// 没有钢板名称
                    r.setStorehouseId(e.getStoragePlace());// 没有垛位
                    r.setLayer(e.getSeq());
                    r.setNestingDrawing(String.format(projectConfig.getUrlPre(), e.getNestId(), e.getNesting()));
                    r.setTexture(e.getPlateMaterial());
                    r.setNorm(e.getPlateMaterial() + "δ" + e.getPlateThick());
                    // 长(米)*宽(米)*厚*7.85(比重)=公斤
                    r.setWeight(e.getPlateWeight());
                    r.setStatus(e.getPlateState());
                    r.setPlanStartDateTime(e.getPlannedStartTime());
                    r.setPlanEndDateTime(e.getPlannedStartTime().plusMinutes(10));
                    r.setOutDateTime(e.getOutTime());
                    r.setPickUserId(e.getPickUserId());
                    r.setPickUserName(e.getPickUserName());
                    r.setPickDateTime(e.getPickDateTime());
                    r.setOutDateTime(e.getOutTime());
                    r.setPickingListNo(e.getPickingListNo());
                    r.setNestPlateId(e.getNestPlateId());
                    r.setNestId(e.getNestId());


                    SinoCamReceiveNestPlate sinoCamReceiveNestPlate = map.get(r.getMaterCode());


                    return r;
                })
                .collect(Collectors.toList());


        return new BasePageResVo<>(page.getTotal(), collect);

    }

    public List<WmsPlatePick> getWmsPlatePicks(List<WmsPlatePick> platePickList) {
        BigDecimal max = new BigDecimal(42 * 1000);
        Map<String, List<WmsPlatePick>> nestMap = platePickList.stream().collect(Collectors.groupingBy(WmsPlatePick::getNestId));

        List<WmsPlatePick> temp = new ArrayList<>();

        for (WmsPlatePick wmsPlatePick : platePickList) {

            if (!wmsPlatePick.getPlateState().equals(1)) {
                throw SyExceptionUtils.e("状态不正确");
            }

            List<WmsPlatePick> wmsPlatePicks = nestMap.get(wmsPlatePick.getNestId());

            if(wmsPlatePicks.size() == 2){
                if(wmsPlatePicks.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(b.getPlateWeight()), BigDecimal::add)
                        .add(temp.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(b.getPlateWeight()), BigDecimal::add))
                        .compareTo(max) <= 0) {

                    temp.addAll(wmsPlatePicks);
                }
            } else {
                BigDecimal sum = temp.stream().reduce(BigDecimal.ZERO, (a, b) -> a.add(b.getPlateWeight()), BigDecimal::add);
                if(sum.add(wmsPlatePick.getPlateWeight())
                        .compareTo(max) <= 0){
                    temp.add(wmsPlatePick);
                } else {
                    break;
                }
            }
        }
        return temp;
    }

    public BaseListResVo<PlatePartListResVo> partList(PlatePartListReqVo reqVo) {

        // 出库传的是钢板ID
        SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.lambdaQuery().eq(SinoCamReceiveNestPlate::getId, reqVo.getId()).one();

        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getReceiveNestId, nestPlate.getReceiveNestId()).list();

        Set<Integer> workDetailIds = nestParts.stream().map(SinoCamReceiveNestPart::getNestPlanId).map(Integer::parseInt).collect(Collectors.toSet());
        List<ApsWorkDetail> workDetails = ChainWrappers.lambdaQueryChain(apsWorkDetailMapper).in(ApsWorkDetail::getId, workDetailIds).list();

        Map<Integer, ApsWorkDetail> map = workDetails.stream().collect(Collectors.toMap(ApsWorkDetail::getId, Function.identity()));

        Map<Integer, Order> orderMap = ChainWrappers.lambdaQueryChain(orderMapper)
                .in(Order::getId, workDetails.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(Order::getId, Function.identity()));
        Map<Integer, ApsOrder> apsOrderMap = ChainWrappers.lambdaQueryChain(apsOrderMapper)
                .in(ApsOrder::getId, workDetails.stream().map(ApsWorkDetail::getApsOrderId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(ApsOrder::getId, Function.identity()));

        Map<Integer, ApsWorkOrder> apsWorkOrderMap = ChainWrappers.lambdaQueryChain(apsWorkOrderMapper)
                .in(ApsWorkOrder::getId, workDetails.stream().map(ApsWorkDetail::getApsWorkOrderId).distinct().collect(Collectors.toList()))
                .list()
                .stream()
                .collect(Collectors.toMap(ApsWorkOrder::getId, Function.identity()));


        List<PlatePartListResVo> collect = nestParts.stream()
                .map(e -> {
                    ApsWorkDetail apsWorkDetail = map.get(Integer.parseInt(e.getNestPlanId()));
                    Order order = orderMap.get(apsWorkDetail.getOrderId());
                    ApsOrder apsOrder = apsOrderMap.get(apsWorkDetail.getApsOrderId());
                    ApsWorkOrder apsWorkOrder = apsWorkOrderMap.get(apsWorkDetail.getApsWorkOrderId());


                    PlatePartListResVo r = new PlatePartListResVo();
                    r.setOrderCode(order.getOrderCode());
                    r.setConstructNo(order.getConstructNo());
                    r.setWorkOrderCode(apsWorkOrder.getWorkOrderCode());
                    r.setSplitNum(apsOrder.getSeq());
                    r.setMaterCode(apsWorkDetail.getMaterNo());
                    r.setMaterName(apsWorkDetail.getMaterName());

//                    String newFileName = apsWorkOrder.getPlmId().substring(0, apsWorkOrder.getPlmId().length() - "_170".length()) + "-XL_170.dxf";
//                    r.setDrawing("ftp://172.31.3.31/dxf-CuttingDiagram/dz_" + order.getConstructNo() + "/" + newFileName);
                    r.setDrawing(e.getPartMapUrl());
                    r.setDimension(String.format("%s * %s * %s", e.getLength() == null?"-":e.getLength(), e.getWidth() == null?"-":e.getWidth(), e.getThickness() == null ? "-" : e.getThickness()));
                    r.setTotalCount(e.getQuantity());
                    r.setWeight(e.getNetWeight());


                    return r;
                })
                .collect(Collectors.toList());

        return new BaseListResVo<>(collect);
    }

    @Transactional
    public void pickJob() {

        // 如果有已领料已下发的，直接跳过
        Integer xiafaCount = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPlateState, 3)
                .count();
        if(xiafaCount > 0){
            return ;
        }

        // 如果有已领料未下发的，则下发关跳过
        Integer pickCount = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPlateState, 2)
                .count();
        if(pickCount > 0){

            List<WmsPlatePick> picks = wmsPlatePickMapper.lambdaQuery().eq(WmsPlatePick::getPlateState, 2).list();
            List<Plate> plateList = plateMapper.lambdaQuery()
                    .in(Plate::getId, picks.stream().map(WmsPlatePick::getPlateId).collect(Collectors.toList()))
                    .list();
////            wmsApiClient.sendLingliao(picks, plateList);
            wmsPlatePickMapper.lambdaUpdate()
                    .in(BaseEntity::getId, picks.stream().map(BaseEntity::getId).collect(Collectors.toList()))
                    .set(WmsPlatePick::getPlateState, 3)
                    .update();

            plateMapper.lambdaUpdate()
                    .in(Plate::getId, picks.stream().map(WmsPlatePick::getPlateId).collect(Collectors.toList()))
                    .set(Plate::getStatus, 3)
                    .update();

            return ;
        }

        // 如果有待打包的，打包,并且下发
        Integer daidabaoCount = wmsPlatePickMapper.lambdaQuery()
                .eq(WmsPlatePick::getPlateState, 1)
                .count();

        if(daidabaoCount <= 0){
            return ;
        }

        List<WmsPlatePick> picks = wmsPlatePickMapper.lambdaQuery().eq(WmsPlatePick::getPlateState, 1).list();

        List<WmsPlatePick> wmsPlatePicks = getWmsPlatePicks(picks);
        List<Plate> plateList = plateMapper.lambdaQuery()
                .in(Plate::getId, picks.stream().map(WmsPlatePick::getPlateId).collect(Collectors.toList()))
                .list();
//        wmsApiClient.sendLingliao(wmsPlatePicks, plateList);

        wmsPlatePickMapper.lambdaUpdate()
                .in(BaseEntity::getId, wmsPlatePicks.stream().map(BaseEntity::getId).collect(Collectors.toList()))
                .set(WmsPlatePick::getPlateState, 3)
                .update();

        plateMapper.lambdaUpdate()
                .in(Plate::getId, wmsPlatePicks.stream().map(WmsPlatePick::getPlateId).collect(Collectors.toList()))
                .set(Plate::getStatus, 3)
                .update();

    }

    @Transactional
    public void outbound(PlateOutboundReqVo reqVo) {
        //通知mes进行钢板出库、
        CompletableFuture.runAsync(()->{
            try {
                apsMesFeign.doPicking(reqVo.getMaterCode());
            } catch (Exception e) {
            }
        });

        List<PlatePhase> platePhases = platePhaseMapper.lambdaQuery().eq(PlatePhase::getPlateCode, reqVo.getMaterCode()).orderByAsc(PlatePhase::getPhaseSeq).list();
        Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode, reqVo.getMaterCode()).one();
//        Result<WorkPlaceUserVo> vo= staffApiClient.getPublicCodeByStation("LL01");
        String staffCode = stationService.getStaffCode(null, "1-1_SC_GBCL_01");

        // 更新领料单状态
        wmsPlatePickMapper.lambdaUpdate()
                .eq(WmsPlatePick::getMaterialId, reqVo.getMaterCode())
                .set(WmsPlatePick::getPlateState, 4)
                .set(WmsPlatePick::getPickDateTime, LocalDateTime.now())
                .set(WmsPlatePick::getPickUserName,staffCode)
                .set(WmsPlatePick::getOutTime, LocalDateTime.now())
                .update();
        ApsWorkDetail llDetail = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getMaterNo, reqVo.getMaterCode()).eq(ApsWorkDetail::getPhaseCode,platePhases.get(0).getPhaseCode()).one();
       if(llDetail.getStatus()!=null&&llDetail.getStatus()==4){
       throw SyExceptionUtils.e("钢板{}已领料出库，禁止重复领料",reqVo.getMaterCode());
       }
        llDetail.setStatus(4);
        llDetail.setFinishCount(BigDecimal.valueOf(1));
        llDetail.setActualEndDateTime(LocalDateTime.now());
        apsWorkDetailMapper.updateById(llDetail);


        WorkDetailTask llTask = workDetailTaskMapper.lambdaQuery().eq(WorkDetailTask::getMaterCode, reqVo.getMaterCode()).eq(WorkDetailTask::getPhaseCode,platePhases.get(0).getPhaseCode()).one();
        llTask.setActualEndDateTime(LocalDateTime.now());
        llTask.setActualStartDateTime(LocalDateTime.now().minusMinutes(6));
        llTask.setStatus(3);
        llTask.setPlmid( reqVo.getMaterCode());
        llTask.setApsWorkDetailId(llDetail.getId());
        llTask.setFailCount(0);
        llTask.setTotalCount(1);
        llTask.setFinishCount(1);
        llTask.setWeight(plate.getWeight());
        llTask.setWidth(plate.getWidth());
        llTask.setLength(plate.getLength());
        llTask.setNestId(plate.getNestId());
        llTask.setPartPath(plate.getNestingDrawing());
        llTask.setPlateCode(reqVo.getMaterCode());
        llTask.setNextPhaseCode(platePhases.get(1).getPhaseCode());
        llTask.setNextGroupCode(platePhases.get(1).getGroupCode());
        workDetailTaskMapper.updateById(llTask);

        WorkRecord workRecord = new WorkRecord();
        workRecord.setPlmid( plate.getNestId());
        workRecord.setPhaseCode((platePhases.get(0).getPhaseCode()));
        workRecord.setWorkDate(LocalDate.now());
        workRecord.setWorkType(2);
        workRecord.setType(1);
        workRecord.setErpState(0);
        workRecord.setTotalCount(1);
        workRecord.setFailCount(0);
        workRecord.setSuccessCount(1);
        workRecord.setWorkStaffCode(staffCode);
        workRecord.setStationCode("LL01");
        workRecord.setGroupNumber(platePhases.get(0).getGroupCode());
        workRecord.setPalletNumber(reqVo.getMaterCode());
        workRecord.setOperationId(llTask.getId());
        workRecord.setApsWorkDetailId(llTask.getApsWorkDetailId());
        workRecord.setStartTime(LocalDateTime.now());
        workRecord.setWorkTime(LocalDateTime.now());
        workRecord.setApsWorkDetailId(llDetail.getId());
        workRecordMapper.insert(workRecord);
        // 开启钢板的待办工单

        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPlateCode,  reqVo.getMaterCode()).list();
        Set<Integer> orderIds = new HashSet<>();

        for(SinoCamReceiveNestPart nestPart:  nestParts){
            ApsWorkDetail qgWrkDetail = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getId, nestPart.getNestPlanId()).one();
            ApsWorkOrder workOrder = apsWorkOrderMapper.lambdaQuery().eq(ApsWorkOrder::getId, qgWrkDetail.getApsWorkOrderId()).one();
            if(workOrder.getStatus()<3){
                workOrder.setStatus(3);
                workOrder.setActualStartDateTime(LocalDateTime.now());
                apsWorkOrderMapper.updateById(workOrder);
            }
            orderIds.add(workOrder.getOrderId());
            ApsWorkDetail llApsWorkDetail = new ApsWorkDetail();
            llApsWorkDetail = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getApsWorkOrderId, qgWrkDetail.getApsWorkOrderId())
                    .eq(ApsWorkDetail::getType, 2)  .eq(ApsWorkDetail::getPhaseCode,platePhases.get(0).getPhaseCode()).last("  LIMIT 1 ").one();
            if(!ObjectUtils.isEmpty(llApsWorkDetail)){
                //更新零件的计划信息
                apsWorkDetailMapper.lambdaUpdate().eq(ApsWorkDetail::getId, llApsWorkDetail.getId())
                        .set(ApsWorkDetail::getUniqueCode, reqVo.getMaterCode())
                        .set(ObjectUtils.isEmpty(llApsWorkDetail.getActualStartDateTime()),ApsWorkDetail::getActualStartDateTime, LocalDateTime.now())
                        .set(ApsWorkDetail::getActualEndDateTime, LocalDateTime.now())
                        .setSql("finish_count=finish_count+"+nestPart.getQuantity()).update();
                llApsWorkDetail=  partUtilService.updateDetailState(llApsWorkDetail.getId());
            }

        }

        if(plate.getStatus()>=4){
         return;
        }

        // 更新钢板状态
        plate.setPhaseCode(platePhases.get(1).getPhaseCode());
        plate.setPhaseStatus(0);
        plate.setStatus(4);
        plateMapper.updateById(plate);


        Map<String, String> map = new HashMap<>();
        map.put(WorkshopProp.YC_PHASE_CODE, "预处理");
        map.put("HG", "火焰切割");
        map.put("JG", "激光切割");
        Part newPart = plateUtils.plateUpdate(plate.getMaterCode(),platePhases.get(1).getPhaseCode(),map.get(platePhases.get(1).getPhaseCode()), platePhases.get(0).getPhaseCode(), plate.getWorkChain(), platePhases.get(1).getGroupCode());
        plateUtils.createPartLog(newPart, platePhases.get(1).getGroupCode(), platePhases.get(1).getGroupCode(),1,null,SySecurityUtils.getUserCode());
       // 生成预处理任务
        List<Order> orders = orderMapper.selectBatchIds(orderIds);
        WorkDetailTask plateTask = new WorkDetailTask();
        plateTask.setMaterCode(plate.getMaterCode());
        plateTask.setPlateCode(plate.getMaterCode());
        plateTask.setPlmid(plate.getMaterCode());
        plateTask.setMaterName(plate.getMaterName());
        plateTask.setPhaseCode( platePhases.get(1).getPhaseCode());
        plateTask.setPhaseName(map.get(platePhases.get(1).getPhaseCode()));
        plateTask.setGroupCode( platePhases.get(1).getGroupCode());
        plateTask.setStatus(1);
        plateTask.setType(1);
        plateTask.setStationCode(WorkshopProp.FIRST_STATION_CODE);
        plateTask.setPlanStartDateTime(plate.getNestDateTime());
        plateTask.setPlanEndDateTime(plateTask.getPlanStartDateTime().plusHours(2));
        plateTask.setOrderCode(orders.stream().map(Order::getConstructNo).distinct().collect(Collectors.joining(",")));
        plateTask.setNorm(plate.getNorm());
        plateTask.setWeight(plate.getWeight());
        plateTask.setWidth(plate.getWidth());
        plateTask.setLength(plate.getLength());
        plateTask.setNestId(plate.getNestId());
        plateTask.setPartPath(plate.getNestingDrawing());
        plateTask.setTexture(plate.getTexture());
        plateTask.setWeight(plate.getNestWeight());
        plateTask.setNestPlateId(plate.getNestPlateId());
        workDetailTaskMapper.insert(plateTask);
        llTask.setOrderCode(plateTask.getOrderCode());
        workDetailTaskMapper.updateById(llTask);
       /* try {
            UpdateNxolpstatusVo dto=new UpdateNxolpstatusVo();
            dto.setNxolnestixno(plate.getNestId());
            apsMesFeign.lockNxolpstatus(dto);
        } catch (Exception e) {
            e.getMessage();
          //  throw new RuntimeException(e);
        }*/
    }
    /**
     * 撤销钢板上的零件计划信息
     * @param plateCode
     */

    @Transactional
    public void backDetail(String plateCode) {

        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery()
                .eq(SinoCamReceiveNestPart::getPlateCode, plateCode)
                .list();
        WorkDetailTask llTask = workDetailTaskMapper.lambdaQuery()
                .eq(WorkDetailTask::getPlmid, plateCode)
                .eq(WorkDetailTask::getType, 1)
                .eq(WorkDetailTask::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                .one();
        if (ObjectUtils.isNotEmpty(llTask) && llTask.getStatus() == 3) {
            for (SinoCamReceiveNestPart nestPart : nestParts) {
                ApsWorkDetail qgWrkDetail = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getId, nestPart.getNestPlanId())
                        .one();
                List<ApsWorkDetail> llApsWorkDetails = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getApsWorkOrderId, qgWrkDetail.getApsWorkOrderId())
                        .eq(ApsWorkDetail::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                        .list();
                int qgcount = nestPart.getQuantity();
                //更新零件的计划信息
                for (ApsWorkDetail ll : llApsWorkDetails) {
                    if (qgcount == 0) {
                        break;
                    }
                    if (ll.getFinishCount() == null) {
                        ll.setFinishCount(new BigDecimal(0));
                    }
                    // 扣减计划完成数量
                    if (ll.getFinishCount().intValue() >= qgcount) {
                        ll.setFinishCount(ll.getFinishCount().subtract(new BigDecimal(qgcount)));
                        qgcount = 0;
                    } else {
                        qgcount = qgcount - ll.getFinishCount().intValue();
                        ll.setFinishCount(new BigDecimal(0));
                    }
                    ll.setStatus(3);
                    apsWorkDetailMapper.updateById(ll);
                }
            }
        }
        WorkDetailTask yCTask = workDetailTaskMapper.lambdaQuery()
                .eq(WorkDetailTask::getPlmid, plateCode)
                .eq(WorkDetailTask::getType, 1)
                .eq(WorkDetailTask::getPhaseCode, WorkshopProp.YC_PHASE_CODE)
                .one();
        if (ObjectUtils.isNotEmpty(yCTask) && yCTask.getStatus() == 3) {
            for (SinoCamReceiveNestPart nestPart : nestParts) {
                ApsWorkDetail qgWrkDetail = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getId, nestPart.getNestPlanId())
                        .one();
                List<ApsWorkDetail> ycApsWorkDetails = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getApsWorkOrderId, qgWrkDetail.getApsWorkOrderId())
                        .eq(ApsWorkDetail::getPhaseCode, WorkshopProp.YC_PHASE_CODE)
                        .list();
                int qgcount = nestPart.getQuantity();
                //更新零件的计划信息
                for (ApsWorkDetail yc : ycApsWorkDetails) {
                    if (qgcount == 0) {
                        break;
                    }
                    if (yc.getFinishCount() == null) {
                        yc.setFinishCount(new BigDecimal(0));
                    }
                    // 扣减计划完成数量
                    if (yc.getFinishCount().intValue() >= qgcount) {
                        yc.setFinishCount(yc.getFinishCount().subtract(new BigDecimal(qgcount)));
                        qgcount = 0;
                    } else {
                        qgcount = qgcount - yc.getFinishCount().intValue();
                        yc.setFinishCount(new BigDecimal(0));
                    }
                    yc.setStatus(3);
                    apsWorkDetailMapper.updateById(yc);
                }
            }
            //删除报工记录
            workRecordMapper.delete(Wrappers.<WorkRecord>lambdaQuery().eq(WorkRecord::getPalletNumber, plateCode).eq(WorkRecord::getType, 2));

        }

    }

    /**
     * 更新钢板上的零件计划信息
     * @param plateCode
     */
    @Transactional
    public void repeatDetail(String plateCode) {

        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery()
                .eq(SinoCamReceiveNestPart::getPlateCode, plateCode)
                .list();
        WorkDetailTask llTask = workDetailTaskMapper.lambdaQuery()
                .eq(WorkDetailTask::getPlmid, plateCode)
                .eq(WorkDetailTask::getType, 1)
                .eq(WorkDetailTask::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                .one();
        if (ObjectUtils.isNotEmpty(llTask) && llTask.getStatus() == 3) {
            for (SinoCamReceiveNestPart nestPart : nestParts) {
                ApsWorkDetail qgWrkDetail = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getId, nestPart.getNestPlanId())
                        .one();
                List<ApsWorkDetail> llApsWorkDetails = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getApsWorkOrderId, qgWrkDetail.getApsWorkOrderId())
                        .eq(ApsWorkDetail::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                        .list();
                int qgcount = nestPart.getQuantity();
                //更新零件的计划信息
                for (ApsWorkDetail ll : llApsWorkDetails) {
                    if (qgcount == 0) {
                        break;
                    }
                    if (ll.getFinishCount() == null) {
                        ll.setFinishCount(new BigDecimal(0));
                    }
                    if (ll.getTotalCount().subtract(ll.getFinishCount()).intValue() >= qgcount) {
                        ll.setFinishCount(ll.getFinishCount().add(new BigDecimal(qgcount)));
                        qgcount = 0;
                    } else {
                        qgcount = qgcount - (ll.getTotalCount().subtract(ll.getFinishCount()).intValue());
                        ll.setFinishCount(ll.getTotalCount());
                    }
                    ll.setActualStartDateTime(LocalDateTime.now());
                    if (ll.getFinishCount().compareTo(ll.getTotalCount()) >= 0) {
                        ll.setActualEndDateTime(LocalDateTime.now());
                        ll.setStatus(4);
                    } else {
                        ll.setStatus(3);
                    }
                    apsWorkDetailMapper.updateById(ll);
                }
            }
        }
        WorkDetailTask yCTask = workDetailTaskMapper.lambdaQuery()
                .eq(WorkDetailTask::getPlmid, plateCode)
                .eq(WorkDetailTask::getType, 1)
                .eq(WorkDetailTask::getPhaseCode, WorkshopProp.YC_PHASE_CODE)
                .one();
        if (ObjectUtils.isNotEmpty(yCTask) && yCTask.getStatus() == 3) {
            for (SinoCamReceiveNestPart nestPart : nestParts) {
                ApsWorkDetail qgApsWorkDetail = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getId, nestPart.getNestPlanId())
                        .one();
                ApsOrder apsOrder = apsOrderMapper.selectById(qgApsWorkDetail.getApsOrderId());
                int qgcount = nestPart.getQuantity();
                List<ApsWorkDetail> ycWorkDetails = apsWorkDetailMapper.lambdaQuery()
                        .eq(ApsWorkDetail::getApsWorkOrderId, qgApsWorkDetail.getApsWorkOrderId())
                        .eq(ApsWorkDetail::getPhaseCode, WorkshopProp.YC_PHASE_CODE)
                        .list();
                for (ApsWorkDetail ycWorkDetail : ycWorkDetails) {
                    if (qgcount == 0) {
                        break;
                    }
                    if (ycWorkDetail.getFinishCount() == null) {
                        ycWorkDetail.setFinishCount(new BigDecimal(0));
                    }
                    String staffCode = SySecurityUtils.getUserCode();
                    if (ycWorkDetail.getTotalCount().subtract(ycWorkDetail.getFinishCount()).intValue() >= qgcount) {
                        partUtilService.complatePartReport(apsOrder.getConstructNo(), ycWorkDetail.getGroupCode(), ycWorkDetail.getGroupCode(), 2, 2,
                                qgApsWorkDetail.getMaterNo(), WorkshopProp.YC_PHASE_CODE, plateCode, qgcount, 0,
                                staffCode, null, ycWorkDetail.getId(), null, null, null);
                        ycWorkDetail.setFinishCount(ycWorkDetail.getFinishCount().add(new BigDecimal(qgcount)));
                        qgcount = 0;
                    } else {
                        partUtilService.complatePartReport(apsOrder.getConstructNo(), ycWorkDetail.getGroupCode(), ycWorkDetail.getGroupCode(), 2, 2,
                                qgApsWorkDetail.getMaterNo(), WorkshopProp.YC_PHASE_CODE, plateCode, ycWorkDetail.getTotalCount().subtract(ycWorkDetail.getFinishCount()).intValue(), 0,
                                staffCode, null, ycWorkDetail.getId(), null, null, null);
                        qgcount = qgcount - (ycWorkDetail.getTotalCount().subtract(ycWorkDetail.getFinishCount()).intValue());
                        ycWorkDetail.setFinishCount(ycWorkDetail.getTotalCount());
                    }
                    ycWorkDetail.setActualStartDateTime(LocalDateTime.now());
                    if (ycWorkDetail.getFinishCount().compareTo(ycWorkDetail.getTotalCount()) >= 0) {
                        ycWorkDetail.setActualEndDateTime(LocalDateTime.now());
                        ycWorkDetail.setStatus(4);
                    } else {
                        ycWorkDetail.setStatus(3);
                    }
                    apsWorkDetailMapper.updateById(ycWorkDetail);

                }


            }


        }

    }

    @Transactional
    public void unOutbound(List<String> materialIds) {
        List<Plate> list = plateMapper.lambdaQuery().in(Plate::getMaterCode, materialIds).list();
        List<Plate> startWorkList = list.stream().filter(e -> e.getStatus() >= 5).collect(Collectors.toList());
        if (!startWorkList.isEmpty()) {
            throw SyExceptionUtils.e("[{}] 钢板已开工", startWorkList.stream().map(Plate::getMaterCode).collect(Collectors.joining(",")));
        }
        // 修改状态
        wmsPlatePickMapper.lambdaUpdate()
                .in(WmsPlatePick::getMaterialId, materialIds)
                .set(WmsPlatePick::getPlateState, 3)
                .set(WmsPlatePick::getOutTime, null)
                .update();
        apsWorkDetailMapper.lambdaUpdate().in(ApsWorkDetail::getMaterNo, materialIds).eq(ApsWorkDetail::getPhaseCode,WorkshopProp.LL_PHASE_CODE)
                .set(ApsWorkDetail::getStatus, 2)
                .set(ApsWorkDetail::getFinishCount,0)
                .set(ApsWorkDetail::getActualEndDateTime, null)
                .update();
        plateMapper.lambdaUpdate()
                .in(Plate::getMaterCode, materialIds)
                .set(Plate::getStatus, 3)
                .set(Plate::getPhaseCode, WorkshopProp.LL_PHASE_CODE)
                .update();
        partMapper.lambdaUpdate().eq(Part::getPartType, 1).in(Part::getPlmId, materialIds)
                .set(Part::getPhaseCode, WorkshopProp.LL_PHASE_CODE).set(Part::getPhaseName, "领料").set(Part::getWorkGroup,"0-1_LL_00").update();
        workRecordMapper.lambdaUpdate()
                .in(WorkRecord::getPlmid, materialIds)
                .eq(WorkRecord::getPhaseCode,WorkshopProp.LL_PHASE_CODE)
                .eq(WorkRecord::getType,1)
                .remove();
        log.info("撤消出库：{}", JsonUtils.toJsonString(startWorkList));
        for(String plateCode: materialIds){
            List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getPlateCode,  plateCode).list();
            for(SinoCamReceiveNestPart nestPart:  nestParts){
                ApsWorkDetail qgWrkDetail = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getId, nestPart.getNestPlanId()).one();
                List<ApsWorkDetail> llApsWorkDetails = apsWorkDetailMapper.lambdaQuery().eq(ApsWorkDetail::getApsWorkOrderId, qgWrkDetail.getApsWorkOrderId()).eq(ApsWorkDetail::getPhaseCode, WorkshopProp.LL_PHASE_CODE).list();
                int qgcount=nestPart.getQuantity();
                //更新零件的计划信息
                for(ApsWorkDetail ll:  llApsWorkDetails){
                    if(qgcount==0){
                        break;
                    }
                    if(ll.getFinishCount().intValue()==0){
                      continue;
                    }
                    if(ll.getFinishCount().intValue()>=qgcount){
                        ll.setFinishCount(ll.getFinishCount().subtract(new BigDecimal(qgcount)));
                        qgcount=0;
                    }else{
                        qgcount=qgcount-ll.getFinishCount().intValue();
                        ll.setFinishCount(new BigDecimal(0));
                    }
                    ll.setActualStartDateTime(LocalDateTime.now());
                    ll.setStatus(3);
                    apsWorkDetailMapper.updateById(ll);
                }
            }
            workDetailTaskMapper.deleteByMaterial(Wrappers.<WorkDetailTask>lambdaQuery().eq(WorkDetailTask::getMaterCode, plateCode).eq(WorkDetailTask::getPhaseCode,WorkshopProp.YC_PHASE_CODE).eq(WorkDetailTask::getType,1));
    }


    }

    public WorkDetailTask initCutting(Plate plate){

        SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.selectById(plate.getNestPlateId());

        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getReceiveNestId, nestPlate.getReceiveNestId()).list();


        List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.selectBatchIds(nestParts.stream().map(SinoCamReceiveNestPart::getNestPlanId).distinct().collect(Collectors.toList()));
        List<Integer> orderIds = apsWorkDetails.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orders = orderMapper.selectBatchIds(orderIds);


        WorkDetailTask plateTask = new WorkDetailTask();
        plateTask.setMaterCode(plate.getMaterCode());
        plateTask.setMaterName(plate.getMaterName());
        plateTask.setPhaseCode(apsWorkDetails.get(0).getPhaseCode());
        plateTask.setPhaseName(apsWorkDetails.get(0).getPhaseName());
        plateTask.setStatus(1);
        plateTask.setGroupCode(apsWorkDetails.get(0).getGroupCode());
        plateTask.setPlanStartDateTime(plate.getNestDateTime());
        plateTask.setPlanEndDateTime(plateTask.getPlanStartDateTime().plusHours(2));
        plateTask.setOrderCode(orders.stream().map(Order::getOrderCode).distinct().collect(Collectors.joining(",")));
        plateTask.setNorm(plate.getNorm());
        plateTask.setTexture(plate.getTexture());
        plateTask.setWeight(plate.getWeight());
        plateTask.setNestPlateId(nestPlate.getId());

        workDetailTaskMapper.insert(plateTask);

        return plateTask;

    }

    public WorkDetailTask initPreprocessing(Plate plate){

        SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.selectById(plate.getNestPlateId());
        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getReceiveNestId, nestPlate.getReceiveNestId()).list();
        List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.selectBatchIds(nestParts.stream().map(SinoCamReceiveNestPart::getNestPlanId).distinct().collect(Collectors.toList()));
        List<Integer> orderIds = apsWorkDetails.stream().map(ApsWorkDetail::getOrderId).distinct().collect(Collectors.toList());
        List<Order> orders = orderMapper.selectBatchIds(orderIds);
        WorkDetailTask plateTask = new WorkDetailTask();
        plateTask.setMaterCode(plate.getMaterCode());
        plateTask.setMaterName(plate.getMaterName());
        plateTask.setPhaseCode(WorkshopProp.YC_PHASE_CODE);
        plateTask.setPhaseName("预处理");
        plateTask.setStatus(1);
        plateTask.setGroupCode(WorkshopProp.YC_GROUP);
        plateTask.setPlanStartDateTime(plate.getNestDateTime());
        plateTask.setPlanEndDateTime(plateTask.getPlanStartDateTime().plusHours(2));
        plateTask.setOrderCode(orders.stream().map(Order::getOrderCode).distinct().collect(Collectors.joining(",")));
        plateTask.setOrderCode(null);
        plateTask.setNorm(plate.getNorm());
        plateTask.setTexture(plate.getTexture());
        plateTask.setWeight(plate.getWeight());
        plateTask.setNestPlateId(nestPlate.getId());
        workDetailTaskMapper.insert(plateTask);

        return plateTask;

    }

    public void makeYcl(String materCode) {
        Plate plate = plateMapper.lambdaQuery().eq(Plate::getMaterCode,materCode).one();
        SinoCamReceiveNestPlate nestPlate = sinoCamReceiveNestPlateMapper.selectById(plate.getNestPlateId());
        List<SinoCamReceiveNestPart> nestParts = sinoCamReceiveNestPartMapper.lambdaQuery().eq(SinoCamReceiveNestPart::getReceiveNestId, nestPlate.getReceiveNestId()).list();
        List<ApsWorkDetail> apsWorkDetails = apsWorkDetailMapper.selectBatchIds(nestParts.stream().map(SinoCamReceiveNestPart::getNestPlanId).distinct().collect(Collectors.toList()));




    }
    /**
     * @Description: tb_mes_plate表钢板锁定
     *
     * @author: hejiahui
     * @since: 2025/1/5 14:16
     */
    public void plateLock(UpdateNxolpstatusVo dto) {
        List<Plate> plateList = plateMapper.lambdaQuery().eq(Plate::getNestId, dto.getNxolnestixno()).list();
        List<String> qg = projectConfig.getCuttingProcess();
        if (ObjectUtils.isNotEmpty(plateList)) {
            for (Plate plate : plateList) {
                WorkDetailTask task = workDetailTaskMapper.lambdaQuery()
                        .eq(WorkDetailTask::getPlmid, plate.getMaterCode())
                        .in(WorkDetailTask::getPhaseCode, qg)
                        .one();
                if (ObjectUtils.isNotEmpty(task) && task.getStatus() == 3) {
                    throw SyExceptionUtils.e("此钢板已切割报工：{}", plate.getMaterCode());
                }
                plate.setNestLock(1);
                plateMapper.updateById(plate);
            }
        }
    }
}
